package cn.iocoder.yudao.module.of.service.schedulecenter;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.iocoder.yudao.framework.common.core.SysConstants;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper;
import cn.iocoder.yudao.module.infra.service.job.JobService;
import cn.iocoder.yudao.module.of.controller.admin.schedulecenter.vo.*;
import cn.iocoder.yudao.module.of.controller.admin.taskhandler.vo.TaskHandlerRespVO;
import cn.iocoder.yudao.module.of.controller.admin.taskinfo.vo.TaskInfoRespVO;
import cn.iocoder.yudao.module.of.dal.dataobject.meetingInfo.MeetingInfoDO;
import cn.iocoder.yudao.module.of.dal.dataobject.schedulecenter.ScheduleCenterDO;
import cn.iocoder.yudao.module.of.dal.dataobject.schedulepart.SchedulePartDO;
import cn.iocoder.yudao.module.of.dal.dataobject.taskapprovals.TaskApprovalDO;
import cn.iocoder.yudao.module.of.dal.dataobject.taskhandler.TaskHandlerDO;
import cn.iocoder.yudao.module.of.dal.dataobject.taskinfo.TaskInfoDO;
import cn.iocoder.yudao.module.of.dal.mysql.meetingInfo.MeetingInfoMapper;
import cn.iocoder.yudao.module.of.dal.mysql.schedulecenter.ScheduleCenterMapper;
import cn.iocoder.yudao.module.of.dal.mysql.schedulepart.SchedulePartMapper;
import cn.iocoder.yudao.module.of.dal.mysql.taskhandler.TaskHandlerMapper;
import cn.iocoder.yudao.module.of.dal.mysql.taskinfo.TaskInfoMapper;
import cn.iocoder.yudao.module.of.enums.*;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.UserDeptDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.UserDeptMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.of.enums.ErrorCodeConstants.SCHEDULE_CENTER_NOT_EXISTS;

/**
 * 日程中心 信息 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
@Log4j2
public class ScheduleCenterServiceImpl implements ScheduleCenterService {

    @Resource
    private ScheduleCenterMapper scheduleCenterMapper;

    @Resource
    private JobService jobService;
    @Resource
    private JobMapper jobMapper;

    @Resource
    private SchedulerManager schedulerManager;
    @Resource
    private DeptMapper deptMapper;
    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private TenantService tenantService;
    @Resource
    private FileMapper fileMapper;
    @Resource
    private DeptService deptService;
    @Resource
    private SchedulePartMapper schedulePartMapper;
    @Resource
    private TaskHandlerMapper taskHandlerMapper;
    @Resource
    private TaskInfoMapper taskInfoMapper;
    @Resource
    private MeetingInfoMapper meetingInfoMapper;
    @Resource
    private UserDeptMapper userDeptMapper;


    @Override
    public Long createScheduleCenter(ScheduleCenterSaveReqVO createReqVO) {
        // 插入
        ScheduleCenterDO scheduleCenter = BeanUtils.toBean(createReqVO, ScheduleCenterDO.class);

        LocalDateTime localDateTime = calcRemindTime(createReqVO);
        scheduleCenter.setRemindTime(localDateTime);
        scheduleCenter.setCategory(ScheduleTypeEnum.SCHEDULE.getCode());

        if (localDateTime != null
                && createReqVO.getRepeatPeriod() != null && createReqVO.getRepeatPeriod() != 1) {
            String crons = getRemindCron(createReqVO);
            log.info("+crons:" + crons);
            JobSaveReqVO reqVO = new JobSaveReqVO();
            reqVO.setName(createReqVO.getTitle());
            reqVO.setHandlerName("scheduleRemindJob");
            reqVO.setRetryCount(1);
            reqVO.setRetryInterval(3);
            reqVO.setCronExpression(crons);
            reqVO.setMonitorTimeout(0);
            JSONObject params = new JSONObject();
            params.put("repeatPeriod", createReqVO.getRepeatPeriod());
            reqVO.setHandlerParam(params.toJSONString());
            try {
                Long jobId = jobService.createJob(reqVO);
                scheduleCenter.setJobId(jobId);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }

        log.info("+scheduleCenter" + JSONObject.toJSONString(scheduleCenter));
//        Set<Long> attachments = scheduleCenter.getAttachments();
//        if(attachments != null && !attachments.isEmpty()) {
//            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, attachments);
//            if (!fileDOS.isEmpty()) {
//                scheduleCenter.setAttachmentList(fileDOS);
//            }
//        }
        scheduleCenterMapper.insert(scheduleCenter);

        Set<String> participants = scheduleCenter.getParticipants();
        List<SchedulePartDO> list = new ArrayList<>();
        for (String part : participants) {
            if (!part.contains("-")) {
                continue;
            }
            String[] split = part.split("-");
            SchedulePartDO partDO = new SchedulePartDO();
            partDO.setDeptId(Long.valueOf(split[0]));
            partDO.setUserId(Long.valueOf(split[1]));
            partDO.setScId(scheduleCenter.getId());
            partDO.setDeptUserId(part);
            list.add(partDO);
        }
        if (!list.isEmpty()) {
            schedulePartMapper.insert(list);
        }
        // 返回
        return scheduleCenter.getId();
    }

    private String getRemindCron(ScheduleCenterSaveReqVO createReqVO) {
        //获取第一次提醒时间点
        LocalDateTime localDateTime = calcRemindTime(createReqVO);
       /* 1	不重复	1
        2	每天	2
        3	每周	3
        4	每月	4
        5	每年	5
        */
        String crons = "";
        Integer repeatPeriod = createReqVO.getRepeatPeriod();
        switch (repeatPeriod.intValue()) {
            case 2: //每日（每日12点提醒 0 0 12 * * ? ）
            case 6: //每日工作日提醒（每日12点提醒 0 0 12 * * ? ）
                crons = localDateTime.getSecond() + " " + localDateTime.getMinute() + " " + localDateTime.getHour()
                        + " * * ? ";
                break;
            case 3: //当前时间 每周提醒 （每周一 12点提醒 0 0 12 ? * MON ）
                crons = localDateTime.getSecond() + " " + localDateTime.getMinute() + " " + localDateTime.getHour() +
                        " ? * " + localDateTime.getDayOfWeek().getValue();
                break;
            case 4: //当月的的某个时刻执行 每月 5号 12点执行（0 0 12 5 * ?
                crons = localDateTime.getSecond() + " " + localDateTime.getMinute() + " " + localDateTime.getHour() +
                        " " + localDateTime.getDayOfMonth() + " * ?";
                break;
            case 5: //当年的的某个时刻执行
                crons = localDateTime.getSecond() + " " + localDateTime.getMinute() + " " + localDateTime.getHour() +
                        " " + localDateTime.getDayOfMonth() + " " + localDateTime.getMonthValue() + "?";
                break;
            case 7: //每小时提醒
                crons = localDateTime.getSecond() + " " + localDateTime.getMinute() +
                        " * * * ? ";
                break;
            default:
                crons = "";
        }

        return crons;
    }

    private LocalDateTime calcRemindTime(ScheduleCenterSaveReqVO createReqVO) {
        DateTime st = createReqVO.getStartTime();
        LocalDateTime startTime = st.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

        Integer remindTimeType = createReqVO.getRemindTimeType();
        switch (remindTimeType.intValue()) {
            case 1:
                return null;
//           case 2:
//               return startTime;
            case 3:
                return startTime.minusMinutes(RemindPointEnum.BEFORE_5_REMIND.getTime());
            case 4:
                return startTime.minusMinutes(RemindPointEnum.BEFORE_15_REMIND.getTime());
            case 5:
                return startTime.minusMinutes(RemindPointEnum.BEFORE_30_REMIND.getTime());
            case 6:
                return startTime.minusMinutes(RemindPointEnum.BEFORE_60_REMIND.getTime());
            case 7:
                return startTime.minusMinutes(RemindPointEnum.BEFORE_120_REMIND.getTime());
            default:
                return startTime;
        }

    }

    @Override
    public void updateScheduleCenter(ScheduleCenterSaveReqVO updateReqVO) {
        // 校验存在
        ScheduleCenterDO scheduleCenterDO = validateScheduleCenterExists(updateReqVO.getId());
        // 更新
        ScheduleCenterDO scheduleCenter = BeanUtils.toBean(updateReqVO, ScheduleCenterDO.class);
        LocalDateTime localDateTime = calcRemindTime(updateReqVO);
        scheduleCenter.setRemindTime(localDateTime);
        if (localDateTime != null
                && updateReqVO.getRepeatPeriod() != null && updateReqVO.getRepeatPeriod() != 1) {
            Long jobId = scheduleCenterDO.getJobId();
            if (jobId != null) {
                String crons = getRemindCron(updateReqVO);
                log.info("+crons:" + crons);
                JobSaveReqVO reqVO = new JobSaveReqVO();
                reqVO.setId(jobId);
                reqVO.setName(updateReqVO.getTitle());
                reqVO.setHandlerName("scheduleRemindJob");
                reqVO.setRetryCount(1);
                reqVO.setRetryInterval(3);
                reqVO.setCronExpression(crons);
                reqVO.setMonitorTimeout(0);
                try {
                    jobService.updateJob(reqVO);
                } catch (SchedulerException e) {
                    e.printStackTrace();
                }
            }
        }
//        Set<Long> attachments = scheduleCenter.getAttachments();
//        if(attachments != null && !attachments.isEmpty()) {
//            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, attachments);
//            if (!fileDOS.isEmpty()) {
//                scheduleCenter.setAttachmentList(fileDOS);
//            }
//        }
        scheduleCenterMapper.updateById(scheduleCenter);
        schedulePartMapper.delete(SchedulePartDO::getScId, updateReqVO.getId());
        Set<String> participants = scheduleCenter.getParticipants();
        List<SchedulePartDO> list = new ArrayList<>();
        for (String part : participants) {
            String[] split = part.split("-");
            SchedulePartDO partDO = new SchedulePartDO();
            partDO.setDeptId(Long.valueOf(split[0]));
            partDO.setUserId(Long.valueOf(split[1]));
            partDO.setScId(scheduleCenter.getId());
            partDO.setDeptUserId(part);
            list.add(partDO);
        }
        if (!list.isEmpty()) {
            schedulePartMapper.insert(list);
        }
    }

    @Override
    public void deleteScheduleCenter(Long id) {
        // 校验存在
        validateScheduleCenterExists(id);
        // 删除
        scheduleCenterMapper.deleteById(id);
    }

    private ScheduleCenterDO validateScheduleCenterExists(Long id) {
        ScheduleCenterDO scheduleCenterDO = scheduleCenterMapper.selectById(id);
        if (scheduleCenterDO == null) {
            throw exception(SCHEDULE_CENTER_NOT_EXISTS);
        }
        return scheduleCenterDO;
    }

    @Override
    public ScheduleCenterRespVO getScheduleCenter(Long id) {
        ScheduleCenterDO scheduleCenterDO = scheduleCenterMapper.selectById(id);

        ScheduleCenterRespVO scheduleCenterRespVO = BeanUtils.toBean(scheduleCenterDO, ScheduleCenterRespVO.class);
        if (scheduleCenterDO.getAttachments() != null) {
            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, scheduleCenterDO.getAttachments());
            scheduleCenterRespVO.setAttachmentList(fileDOS);
        }
        List<String> partNameList = new ArrayList();
        List<String> participants = scheduleCenterRespVO.getParticipants();
        if(participants != null){
           for(String part:participants){
                if(part.contains("-")){
                    String userId = part.split("-")[1];
                    AdminUserDO adminUserDO = userMapper.selectById(userId);
                    if(adminUserDO != null){
                        partNameList.add(adminUserDO.getNickname());
                    }
                }
            }
        }
        scheduleCenterRespVO.setParticipantsName(partNameList);
        AdminUserDO adminUserDO = userMapper.selectById(scheduleCenterDO.getCreator());
        if (adminUserDO != null) {
            scheduleCenterRespVO.setCreatorName(adminUserDO.getNickname());
        }
        return scheduleCenterRespVO;
    }

    @Override
    public TaskInfoRespVO getTaskInfo(Long id) {
        TaskInfoDO taskInfoDO = taskInfoMapper.selectById(id);
        TaskInfoRespVO taskInfoRespVO = BeanUtils.toBean(taskInfoDO, TaskInfoRespVO.class);
        List<Long> taskAttachment = taskInfoDO.getTaskAttachment();
        if (taskAttachment != null && !taskAttachment.isEmpty()) {
            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, taskAttachment);
            taskInfoRespVO.setTaskAttachmentList(fileDOS);
        }
        List<Long> taskDocFile = taskInfoDO.getTaskDocFile();
        if (taskDocFile != null && !taskDocFile.isEmpty()) {
            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, taskDocFile);
            taskInfoRespVO.setTaskDocFileList(fileDOS);
        }
        taskInfoRespVO.setStatusName(TaskStatusEnum.valueOf(taskInfoRespVO.getStatus(), taskInfoRespVO.getTaskLevel()));
        List<TaskInfoDO> taskInfoDOS = taskInfoMapper.selectList(TaskInfoDO::getParentId, taskInfoDO.getId());
        List<TaskInfoRespVO> children = taskInfoDOS.stream().map(child -> {
            TaskInfoRespVO childRespVO = BeanUtils.toBean(child, TaskInfoRespVO.class);
            if (child.getTaskAttachment() != null && !child.getTaskAttachment().isEmpty()) {
                List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, child.getTaskAttachment());
                childRespVO.setTaskAttachmentList(fileDOS);
            }
            List<Long> childDocFile = child.getTaskDocFile();
            if (childDocFile != null && !childDocFile.isEmpty()) {
                List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, childDocFile);
                childRespVO.setTaskDocFileList(fileDOS);
            }
            childRespVO.setStatusName(TaskStatusEnum.valueOf(childRespVO.getStatus(), childRespVO.getTaskLevel()));
            List<TaskHandlerDO> taskHandlerDOS = taskHandlerMapper.selectList(TaskHandlerDO::getTaskId, child.getId());
            List<TaskHandlerRespVO> taskHandlerList = taskHandlerDOS.stream().map(th -> {
                TaskHandlerRespVO taskHandlerRespVO = BeanUtils.toBean(th, TaskHandlerRespVO.class);
                AdminUserDO adminUserDO = userMapper.selectById(th.getUserId());
                if (adminUserDO != null) {
                    taskHandlerRespVO.setUserName(adminUserDO.getNickname());
                }
                DeptDO deptDO = deptMapper.selectById(th.getDeptId());
                if (deptDO != null) {
                    taskHandlerRespVO.setDeptName(deptDO.getName());
                }
                return taskHandlerRespVO;
            }).collect(Collectors.toList());

            childRespVO.setTaskHandlerList(taskHandlerList);


            return childRespVO;
        }).collect(Collectors.toList());
        taskInfoRespVO.setChildren(children);

        List<TaskHandlerDO> taskHandlerDOS = taskHandlerMapper.selectList(TaskHandlerDO::getTaskId, id);
        List<TaskHandlerRespVO> taskHandlerList = taskHandlerDOS.stream().map(th -> {
            TaskHandlerRespVO taskHandlerRespVO = BeanUtils.toBean(th, TaskHandlerRespVO.class);
            AdminUserDO adminUserDO = userMapper.selectById(th.getUserId());
            if (adminUserDO != null) {
                taskHandlerRespVO.setUserName(adminUserDO.getNickname());
            }
            DeptDO deptDO = deptMapper.selectById(th.getDeptId());
            if (deptDO != null) {
                taskHandlerRespVO.setDeptName(deptDO.getName());
            }
            return taskHandlerRespVO;
        }).collect(Collectors.toList());

        taskInfoRespVO.setTaskHandlerList(taskHandlerList);

        return taskInfoRespVO;
    }

    @Override
    public PageResult<ScheduleCenterRespVO> getScheduleCenterPage(ScheduleCenterPageReqVO pageReqVO) {
        PageResult<ScheduleCenterDO> scheduleCenterDOPageResult = scheduleCenterMapper.selectPage(pageReqVO);
        List<ScheduleCenterDO> list = scheduleCenterDOPageResult.getList();
        List<ScheduleCenterRespVO> resultList = new ArrayList<>();

        for (ScheduleCenterDO scd : list) {
            ScheduleCenterRespVO scheduleCenterRespVO = BeanUtils.toBean(scd, ScheduleCenterRespVO.class);
            if (scd.getAttachments() != null) {
                List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, scd.getAttachments());
                scheduleCenterRespVO.setAttachmentList(fileDOS);
            }
            resultList.add(scheduleCenterRespVO);
        }
        return new PageResult().setList(resultList).setTotal(scheduleCenterDOPageResult.getTotal());
    }

    /**
     * 日历查询  月和年
     */
    @Override
    public List<ScheduleCenterRespVO> getScheduleCenterList(ScheduleCenterPageReqVO pageReqVO) {
        List<ScheduleCenterRespVO> resultList = getCalendarScheduleCenter(pageReqVO);

        List<ScheduleCenterRespVO> meeting = getCalendarMeeting(pageReqVO);
        if (!meeting.isEmpty()) {
            resultList.addAll(meeting);
        }

        List<ScheduleCenterRespVO> calendarTask = getCalendarTask(pageReqVO);
        if (!calendarTask.isEmpty()) {
            resultList.addAll(calendarTask);
        }

        Collections.sort(resultList, new Comparator<ScheduleCenterRespVO>() {
            public int compare(ScheduleCenterRespVO m1, ScheduleCenterRespVO m2) {
                return m2.getStartTime().compareTo(m1.getStartTime());
            }
        });

        return resultList;
    }


    @Override
    public JSONObject getListGroupDay(ScheduleCenterPageReqVO pageReqVO) {
        //按天查询
        JSONObject result = new JSONObject();
        if (pageReqVO.getTimeType() == TimeTypeConstants.QUERY_PERIOD_DAY) {
            DateTime dateTime = pageReqVO.getCreateTime()[0];
            //获取 日历 （天） 数据
            List<ScheduleCenterRespVO> scList = getCalarderDayData(pageReqVO);

            // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String s = dateTime.toString();
            result.put(s, scList);
        } else if (pageReqVO.getTimeType() == TimeTypeConstants.QUERY_PERIOD_WEEK) {
            DateTime[] createTime = pageReqVO.getCreateTime();

            DateTime start = pageReqVO.getCreateTime()[0];
            DateTime end = pageReqVO.getCreateTime()[1];


            LocalDateTime localStartTime = start.toLocalDateTime();
            LocalDateTime localEndTime = end.toLocalDateTime();

            for (int i = 0; i < 5; i++) {
                DateTime st = new DateTime();
                DateTime ed = new DateTime();
                if (i == 0) {
                    // LocalDateTime localStartTime =   localStartTime;
                    localEndTime = localStartTime.plusDays(1);

                } else {
                    localStartTime = localStartTime.plusDays(1);
                    localEndTime = localEndTime.plusDays(1);
                }
                // localStartTime =   localStartTime.plusDays(i);
                // localEndTime =    localStartTime.plusDays(i+1);
                log.info("localStartTime:::" + localStartTime);
                log.info("localEndTime:::" + localEndTime);
                st.setField(DateField.YEAR, localStartTime.getYear());
                st.setField(DateField.MONTH, localStartTime.getMonthValue() - 1);
                st.setField(DateField.DAY_OF_MONTH, localStartTime.getDayOfMonth());
                st.setField(DateField.HOUR, localStartTime.getHour());
                st.setField(DateField.MINUTE, localStartTime.getMinute());
                st.setField(DateField.SECOND, localStartTime.getSecond());
                log.info("st:::" + st);

                ed.setField(DateField.YEAR, localEndTime.getYear());
                ed.setField(DateField.MONTH, localEndTime.getMonthValue() - 1);
                ed.setField(DateField.DAY_OF_MONTH, localEndTime.getDayOfMonth());
                ed.setField(DateField.HOUR, localEndTime.getHour());
                ed.setField(DateField.MINUTE, localEndTime.getMinute());
                ed.setField(DateField.SECOND, localEndTime.getSecond());
                log.info("ed:::" + ed);
                createTime[0] = st;
                createTime[1] = ed;
                pageReqVO.setCreateTime(createTime);
                pageReqVO.setTimeType(1);//转成按日查询

                List<ScheduleCenterRespVO> scList = getCalarderDayData(pageReqVO);
                result.put(st.toString(), scList);
            }
        }

        return result;
    }

    private List<ScheduleCenterRespVO> getCalarderDayData(ScheduleCenterPageReqVO pageReqVO) {
        ScheduleCenterPageReqVO scVo = new ScheduleCenterPageReqVO();
        scVo.setCreateTime(pageReqVO.getCreateTime());
        scVo.setTitle(pageReqVO.getTitle());
        List<ScheduleCenterRespVO> scList = getCalendarScheduleCenter(scVo);

        List<ScheduleCenterRespVO> meetingList = getCalendarMeeting(scVo);
        if (!meetingList.isEmpty()) {
            scList.addAll(meetingList);
        }

        // 获取处理中的任务 8:00：00 8:23:59:59   end :8:12:00:00
        List<ScheduleCenterRespVO> taskList = getCalendarTaskHanding(pageReqVO);
        if (!taskList.isEmpty()) {
            scList.addAll(taskList);
        }
        //获取当天截止的任务
        List<ScheduleCenterRespVO> task1List = getCalendarTask(pageReqVO);
        if (!task1List.isEmpty()) {
            scList.addAll(task1List);
        }

        return scList;
    }

    @Override
    public JSONObject getScheduleCenterBoradList(ScheduleCenterBordReqVo reqVO) {

        log.info("getScheduleCenterBoradList::" + JSONObject.toJSONString(reqVO));
        JSONObject result = new JSONObject();

        LocalDate startTime = null;
        LocalDate endTime = null;
        LocalDate currentDay = null;
        if (reqVO.getTimeType() != null && reqVO.getTimeType() == TimeTypeConstants.QUERY_PERIOD_DAY) {
            //日看板
            LocalDate time = reqVO.getTime().toLocalDateTime().toLocalDate();
            if (time == null) {
                time = LocalDate.now();
            }
            currentDay = LocalDate.from(time);
            log.info("time:" + time);
            startTime = time.minusDays(1);
            endTime = time.plusDays(9);//不包含第9点
            log.info("startTime:" + startTime + " endTime:" + endTime);
            result.put(BoardGropEnum.YESTERDAY.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.TODAY.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.TOMORROW.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.AFTER_7_DAY.getCode(), new ArrayList<>());
        } else if (reqVO.getTimeType() != null && reqVO.getTimeType() == TimeTypeConstants.QUERY_PERIOD_WEEK) {
            //周看板
            LocalDate time = reqVO.getTime().toLocalDateTime().toLocalDate();
            if (time == null) {
                time = LocalDate.now();
            }
            currentDay = LocalDate.from(time);
            LocalDate startOfWeek = time.with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY));
            LocalDate endOfWeek = time.with(TemporalAdjusters.nextOrSame(java.time.DayOfWeek.SUNDAY));
            startTime = startOfWeek.minusDays(7);
            endTime = endOfWeek.plusDays(15);//不包含第十五天
            log.info("startTime:" + startTime + " endTime:" + endTime);
            result.put(BoardGropEnum.PREV_WEEK.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.CURRENT_WEEK.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.NEXT_WEEK.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.NEXT2_WEEK.getCode(), new ArrayList<>());
        } else if (reqVO.getTimeType() != null && reqVO.getTimeType() == TimeTypeConstants.QUERY_PERIOD_MONTH) {
            //月看板
            LocalDate time = reqVO.getTime().toLocalDateTime().toLocalDate();
            if (time == null) {
                time = LocalDate.now();
            }
            currentDay = LocalDate.from(time);
            LocalDate startOfMonth = time.withDayOfMonth(1);
            LocalDate nextMonth = startOfMonth.plusMonths(1);
            LocalDate endOfMonth = nextMonth.minusDays(1);
            startTime = startOfMonth.minusMonths(1);
            endTime = endOfMonth.plusMonths(2);
            log.info("startTime month:" + startTime + " endTime month:" + endTime);
            result.put(BoardGropEnum.PREV_WEEK.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.CURRENT_WEEK.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.NEXT_WEEK.getCode(), new ArrayList<>());
            result.put(BoardGropEnum.NEXT2_WEEK.getCode(), new ArrayList<>());
        } else {
            //年看板
            LocalDate time = reqVO.getTime().toLocalDateTime().toLocalDate();
            if (time == null) {
                time = LocalDate.now();
            }

            startTime = LocalDate.of(time.getYear(), 1, 1);
            endTime = LocalDate.of(time.getYear(), 12, 31).plusDays(1);
            log.info("startTime month:" + startTime + " endTime month:" + endTime);
            for (int i = 1; i < 13; i++) {
                result.put(i + "", new ArrayList<>());
            }

        }

        queryScheduleCenter(reqVO, currentDay, startTime, endTime, result);
        getBoardMeeting(reqVO, currentDay, startTime, endTime, result);
        queryBoardTask(reqVO, currentDay, startTime, endTime, result);
        return result;
    }

    @Override
    public List getAllYearTaskList(ScheduleCenterBordReqVo reqVO) {
        LocalDate time = reqVO.getTime().toLocalDateTime().toLocalDate();
        if (time == null) {
            time = LocalDate.now();
        }

        LocalDate startTime = LocalDate.of(time.getYear(), 1, 1);
        LocalDate endTime = LocalDate.of(time.getYear(), 12, 31).plusDays(1);
        log.info("startTime month:" + startTime + " endTime month:" + endTime);

        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = new MPJLambdaWrapperX<>();

        //   queryWrapper.geIfPresent(TaskInfoDO::getEndTime,startTime)
        queryWrapper.ltIfPresent(TaskInfoDO::getEndTime, endTime);
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, reqVO.getTitle())
                .neIfPresent(TenantDO::getStatus, TaskStatusEnum.OVER);

        List<UserDeptDO> userDeptDOS = userDeptMapper.selectList(UserDeptDO::getUserId, WebFrameworkUtils.getLoginUserId());
        Boolean flag = false;
        for (UserDeptDO ud : userDeptDOS) {
            if (ud.getDeptId() == SysConstants.JT_LEADER_DEPT.longValue()) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            queryWrapper.eqIfPresent(TaskHandlerDO::getUserId, WebFrameworkUtils.getLoginUserId());
            queryWrapper.innerJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        }
        // queryWrapper.innerJoin(TaskApprovalDO.class,TaskApprovalDO::getTaskId,TaskInfoDO::getId);

        List<TaskInfoDO> taskInfoDOS = taskInfoMapper.selectList(queryWrapper);

        return taskInfoDOS;
    }


    private void queryScheduleCenter(ScheduleCenterBordReqVo reqVO, LocalDate currentDay, LocalDate startTime, LocalDate endTime, JSONObject result) {
        MPJLambdaWrapperX<ScheduleCenterDO> queryWrapper = new MPJLambdaWrapperX<>();
        queryWrapper.distinct();
        queryWrapper.geIfPresent(ScheduleCenterDO::getStartTime, startTime)
                .ltIfPresent(ScheduleCenterDO::getStartTime, endTime);
        queryWrapper.likeIfPresent(ScheduleCenterDO::getTitle, reqVO.getTitle());
        queryWrapper.and(wrap -> wrap.eq(SchedulePartDO::getUserId, WebFrameworkUtils.getLoginUserId())
                .or().eq(ScheduleCenterDO::getCreator, WebFrameworkUtils.getLoginUserId())
        );
        queryWrapper.leftJoin(SchedulePartDO.class, SchedulePartDO::getScId, ScheduleCenterDO::getId);
        List<ScheduleCenterDO> scheduleCenterDOS = scheduleCenterMapper.selectList(queryWrapper);

        for (ScheduleCenterDO sc : scheduleCenterDOS) {
            String key = getKey(reqVO.getTimeType(), sc.getStartTime(), currentDay);
            List s = (List) result.get(key);
            if (s == null) {
                s = new ArrayList();
            }
            ScheduleCenterBordRespVo brv = new ScheduleCenterBordRespVo();
            brv.setId(sc.getId()).setTitle(sc.getTitle()).setStarTime(sc.getStartTime())
                    .setEndTime(sc.getEndTime()).setCategory(1)
                    .setPriorityId(sc.getPriorityId()).setPriorityName(sc.getPriorityName()).setCreator(sc.getCreator());
            Set<Long> attachments = sc.getAttachments();
            if (attachments != null && !attachments.isEmpty()) {
                List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, attachments);
                brv.setAttachmentList(fileDOS);
            }
            s.add(brv);
            result.put(key, s);
        }
    }


    private void getBoardMeeting(ScheduleCenterBordReqVo reqVO, LocalDate currentDay, LocalDate startTime, LocalDate endTime, JSONObject result) {
        MPJLambdaWrapperX<MeetingInfoDO> queryWrapper = new MPJLambdaWrapperX<>();
        //获取MeetingInfoDO 表的别名
        String alias = queryWrapper.getAlias();
        queryWrapper.geIfPresent(MeetingInfoDO::getStartTime, startTime)
                .ltIfPresent(MeetingInfoDO::getStartTime, endTime);
        queryWrapper.likeIfPresent(MeetingInfoDO::getName, reqVO.getTitle());
//        queryWrapper.eqIfPresent(MeetingPartDO::getUserId,WebFrameworkUtils.getLoginUserId());
//        queryWrapper.innerJoin(MeetingPartDO.class,MeetingPartDO::getMeetingId,MeetingInfoDO::getId);
        queryWrapper.and(wrap -> wrap.eq(MeetingInfoDO::getCreator, WebFrameworkUtils.getLoginUserId())
                .or().eq(MeetingInfoDO::getChairpersonId, WebFrameworkUtils.getLoginUserId())
                .or().exists("select 1 from of_meeting_part pt where   " + alias + ".id = pt.meeting_id and pt.user_id =" + WebFrameworkUtils.getLoginUserId())
        );
        List<MeetingInfoDO> meetingList = meetingInfoMapper.selectList(queryWrapper);
        for (MeetingInfoDO mi : meetingList) {
            String key = getKey(reqVO.getTimeType(), mi.getStartTime(), currentDay);
            List s = (List) result.get(key);
            if (s == null) {
                s = new ArrayList();
            }
            ScheduleCenterBordRespVo brv = new ScheduleCenterBordRespVo();
            brv.setId(mi.getId()).setTitle(mi.getName()).setStarTime(mi.getStartTime())
                    .setEndTime(mi.getEndTime()).setCategory(3)
                    .setPriorityName(mi.getPriorityName()).setPriorityId(mi.getPriorityId())
                    .setMeetTypeId(mi.getTypeId());
            s.add(brv);
            result.put(key, s);
        }
    }

    private void queryBoardTask(ScheduleCenterBordReqVo reqVO, LocalDate currentDay, LocalDate startTime, LocalDate endTime, JSONObject result) {
        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = new MPJLambdaWrapperX<>();
        queryWrapper.selectAll(TaskInfoDO.class);
        queryWrapper.geIfPresent(TaskInfoDO::getEndTime, startTime)
                .ltIfPresent(TaskInfoDO::getEndTime, endTime);
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, reqVO.getTitle());
        queryWrapper.eqIfPresent(TaskHandlerDO::getUserId, WebFrameworkUtils.getLoginUserId());
        queryWrapper.innerJoin(TaskApprovalDO.class, TaskApprovalDO::getTaskId, TaskInfoDO::getId);
        queryWrapper.innerJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        List<TaskInfoDO> taskInfoDOS = taskInfoMapper.selectList(queryWrapper);
        for (TaskInfoDO mi : taskInfoDOS) {
            LocalDateTime approvalTime = mi.getEndTime();
            String key = getKey(reqVO.getTimeType(), approvalTime, currentDay);
            List s = (List) result.get(key);
            if (s == null) {
                s = new ArrayList();
            }
            ScheduleCenterBordRespVo brv = new ScheduleCenterBordRespVo();
            brv.setId(mi.getId()).setTitle(mi.getTaskName()).setStarTime(mi.getStartTime()).setEndTime(mi.getEndTime()).setCategory(2)
                    .setPriorityName(mi.getPriorityName()).setPriorityId(mi.getPriorityId());
            s.add(brv);
            result.put(key, s);
        }
    }

    private String getKey(int timeType, LocalDateTime startTime, LocalDate localDate) {
        String key = "";
        if (timeType == TimeTypeConstants.QUERY_PERIOD_DAY) {

            LocalDate cstartTime = localDate.minusDays(2);
            //System.out.println("cstartTime::"+cstartTime);

            /// LocalDate startTime = LocalDateTime.now().plusDays(1).toLocalDate();
            LocalDate stime = startTime.toLocalDate();
            System.out.println("startTime::" + stime);

            for (int i = 1; i < 5; i++) {
               // System.out.println("cstartTime::" + cstartTime);
                cstartTime = cstartTime.plusDays(1);
                LocalDate cendTime = cstartTime.with(cstartTime);
               // System.out.println("cstartTime::" + cstartTime + " cendTime:" + cendTime);
                int i1 = cstartTime.compareTo(stime);
                int i2 = cendTime.compareTo(stime);

                System.out.println("i1::" + i1 + " i2:" + i2);
                if (i1 <= 0 && i2 >= 0) {
                    return i + "";
                }
                if (i == 4) {
                    return "4";
                }

            }
        } else if (timeType == 2) {

//            long until = localDate.until(startTime.toLocalDate(), ChronoUnit.WEEKS);
//            log.info("until week:"+until );
//            if (until == -1) {
//                key = BoardGropEnum.PREV_WEEK.getCode();
//            } else if (until == 0) {
//                key = BoardGropEnum.CURRENT_WEEK.getCode();
//            } else if (until == 1) {
//                key = BoardGropEnum.NEXT_WEEK.getCode();
//            } else {
//                //七天后
//                key =BoardGropEnum.NEXT2_WEEK.getCode();
//            }
            LocalDate cstartTime = localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            cstartTime = cstartTime.minusWeeks(2);
            for (int i = 1; i < 5; i++) {
                cstartTime = cstartTime.plusWeeks(1);
                LocalDate cendTime = cstartTime.with(cstartTime).plusDays(6);
                int i1 = cstartTime.compareTo(startTime.toLocalDate());
                int i2 = cendTime.compareTo(startTime.toLocalDate());
                if (i1 <= 0 && i2 >= 0) {
                    return i + "";
                }

            }

        } else if (timeType == TimeTypeConstants.QUERY_PERIOD_MONTH) {
//            long until = localDate.until(startTime.toLocalDate(), ChronoUnit.MONTHS);
//            log.info("until week:"+until );
//            if (until == -1) {
//                key = BoardGropEnum.PREV_MONTH.getCode();
//            } else if (until == 0) {
//                key = BoardGropEnum.CURRENT_MONTH.getCode();
//            } else if (until == 1) {
//                key = BoardGropEnum.NEXT_MONTH.getCode();
//            } else {
//                //七天后
//                key =BoardGropEnum.NEXT2_MONTH.getCode();
//            }
            LocalDate cstartTime = LocalDate.of(localDate.getYear(), localDate.getMonth(), 1);
            System.out.println("cstartTime::" + cstartTime);
            cstartTime = cstartTime.minusMonths(2);

            for (int i = 1; i < 5; i++) {
                System.out.println("cstartTime::" + cstartTime);
                cstartTime = cstartTime.plusMonths(1);

                LocalDate cendTime = cstartTime.with(cstartTime).plusMonths(1).minusDays(1);
                System.out.println("cstartTime::" + cstartTime + " cendTime:" + cendTime);

                int i1 = cstartTime.compareTo(startTime.toLocalDate());
                int i2 = cendTime.compareTo(startTime.toLocalDate());

                System.out.println("i1::" + i1 + " i2:" + i2);
                if (i1 <= 0 && i2 >= 0) {
                    System.out.println("key::" + i);
                    return i + "";
                }

            }


        } else {
            key = String.valueOf(startTime.getMonthValue());
        }
        return key;
    }

    private List<ScheduleCenterRespVO> getCalendarScheduleCenter(ScheduleCenterPageReqVO pageReqVO) {
        List<ScheduleCenterRespVO> resultList = new ArrayList<>();
        List<ScheduleCenterDO> scheduleCenterDOS = scheduleCenterMapper.selectList(pageReqVO);

        for (ScheduleCenterDO scd : scheduleCenterDOS) {
            ScheduleCenterRespVO scheduleCenterRespVO = BeanUtils.toBean(scd, ScheduleCenterRespVO.class);

            Set<Long> attachments = scd.getAttachments();
            if (attachments != null && !attachments.isEmpty()) {
                List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, attachments);
                scheduleCenterRespVO.setAttachmentList(fileDOS);
            }
            AdminUserDO adminUserDO = userMapper.selectById(scd.getCreator());
            if (adminUserDO != null) {
                scheduleCenterRespVO.setCreatorName(adminUserDO.getNickname());
            }
            resultList.add(scheduleCenterRespVO);
        }
//            List<ScheduleCenterDO> scCreatorList = scheduleCenterMapper.selectListByCreator(pageReqVO);
//            if(!scCreatorList.isEmpty()){
//                List<ScheduleCenterRespVO> collect = scCreatorList.stream().map(item -> BeanUtils.toBean(item, ScheduleCenterRespVO.class))
//                        .collect(Collectors.toList());
//                resultList.addAll(collect);
//            }
        return resultList;
    }

    private List<ScheduleCenterRespVO> getCalendarMeeting(ScheduleCenterPageReqVO pageReqVO) {
        MPJLambdaWrapperX<MeetingInfoDO> queryWrapper = new MPJLambdaWrapperX<>();
        String alias = queryWrapper.getAlias();
        queryWrapper.betweenIfPresent(MeetingInfoDO::getStartTime, pageReqVO.getCreateTime());
        queryWrapper.likeIfPresent(MeetingInfoDO::getName, pageReqVO.getTitle());

        //能查看会议的人，创建者，主持人、参与人
        queryWrapper.and(wrap -> wrap.eq(MeetingInfoDO::getCreator, WebFrameworkUtils.getLoginUserId())
                .or().eq(MeetingInfoDO::getChairpersonId, WebFrameworkUtils.getLoginUserId())
                .or().exists("select 1 from of_meeting_part pt where   " + alias + ".id = pt.meeting_id and pt.user_id =" + WebFrameworkUtils.getLoginUserId())
        );

        List<MeetingInfoDO> meetingList = meetingInfoMapper.selectList(queryWrapper);

        if (meetingList.isEmpty()) {
            return new ArrayList<ScheduleCenterRespVO>();
        }
        List<ScheduleCenterRespVO> collect = meetingList.stream().map(item -> {
            ScheduleCenterRespVO res = new ScheduleCenterRespVO();
            res.setId(item.getId());
            res.setTitle(item.getName());
            res.setStartTime(item.getStartTime());
            res.setEndTime(item.getEndTime());
            res.setCategory(ScheduleTypeEnum.MEETING.getCode());
            res.setCreator(item.getCreator());
            res.setPriorityId(item.getPriorityId());
            res.setPriorityName(item.getPriorityName());
            AdminUserDO adminUserDO = userMapper.selectById(item.getCreator());
            if (adminUserDO != null) {
                res.setCreatorName(adminUserDO.getNickname());
            }

            return res;
        }).collect(Collectors.toList());

        return collect;
    }

    //获取处理中的案件
    private List<ScheduleCenterRespVO> getCalendarTaskHanding(ScheduleCenterPageReqVO pageReqVO) {
        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = new MPJLambdaWrapperX<>();
        queryWrapper.selectAll(TaskInfoDO.class);
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, pageReqVO.getTitle())
                .leIfPresent(TaskInfoDO::getStartTime, pageReqVO.getCreateTime()[0])
                .gtIfPresent(TaskInfoDO::getEndTime, pageReqVO.getCreateTime()[1])
                .eqIfPresent(TaskHandlerDO::getUserId, WebFrameworkUtils.getLoginUserId());
        queryWrapper.innerJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        queryWrapper.orderByDesc(TaskInfoDO::getStartTime);
        List<TaskInfoDO> taskInfoDOS = taskInfoMapper.selectList(queryWrapper);
        if (taskInfoDOS.isEmpty()) {
            return new ArrayList<>();
        }
        List<ScheduleCenterRespVO> collect = taskInfoDOS.stream().map(item -> {
            ScheduleCenterRespVO sc = new ScheduleCenterRespVO();
            sc.setId(item.getId());
            sc.setCategory(ScheduleTypeEnum.TASK.getCode());
            sc.setTitle(item.getTaskName());
            sc.setStartTime(item.getStartTime());
            sc.setEndTime(item.getEndTime());
            sc.setDescription(item.getTaskDesc());
            sc.setPriorityName(item.getPriorityName());
            sc.setPriorityId(item.getPriorityId());

            if (CollectionUtils.isNotEmpty(item.getTaskAttachment())) {
                List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, item.getTaskAttachment());
                sc.setAttachmentList(fileDOS);
            }
            sc.setCreator(item.getCreator());
            AdminUserDO adminUserDO = userMapper.selectById(item.getCreator());
            if (adminUserDO != null) {
                sc.setCreatorName(adminUserDO.getNickname());
            }

            return sc;
        }).collect(Collectors.toList());
        return collect;
    }

    //获取当天的处置的案件
    private List<ScheduleCenterRespVO> getCalendarTask(ScheduleCenterPageReqVO pageReqVO) {
        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = new MPJLambdaWrapperX<>();
        queryWrapper.selectAll(TaskInfoDO.class);
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, pageReqVO.getTitle())
                .betweenIfPresent(TaskInfoDO::getEndTime, pageReqVO.getCreateTime())
                .eqIfPresent(TaskHandlerDO::getUserId, WebFrameworkUtils.getLoginUserId());
        queryWrapper.innerJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        queryWrapper.orderByDesc(TaskInfoDO::getStartTime);
        List<TaskInfoDO> taskInfoDOS = taskInfoMapper.selectList(queryWrapper);
        if (taskInfoDOS.isEmpty()) {
            return new ArrayList<>();
        }
        List<ScheduleCenterRespVO> collect = taskInfoDOS.stream().map(item -> {
            ScheduleCenterRespVO sc = new ScheduleCenterRespVO();
            sc.setId(item.getId());
            sc.setCategory(ScheduleTypeEnum.TASK.getCode());
            sc.setTitle(item.getTaskName());
            sc.setStartTime(item.getStartTime());
            sc.setEndTime(item.getEndTime());
            sc.setDescription(item.getTaskDesc());
            sc.setStatus(item.getStatus());
            sc.setCreator(item.getCreator());
            sc.setPriorityId(item.getPriorityId());
            sc.setCreatorName(item.getPriorityName());
            AdminUserDO adminUserDO = userMapper.selectById(item.getCreator());
            if (adminUserDO != null) {
                sc.setCreatorName(adminUserDO.getNickname());
            }
            return sc;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public List userTree(List<String> userList) {
        List<DeptDO> allDeptList = deptMapper.selectList();
        //scID ==  null 新建任务，获取部门根节点
        if (userList == null || userList.isEmpty()) {
            return getRootDept(allDeptList);
        }

        // ScheduleCenterDO scheduleCenterDO = scheduleCenterMapper.selectById(scId);
        //没有查到日程，当新增处理
//        if (scheduleCenterDO == null) {
//            return getRootDept(allDeptList);
//        }
//        Set<String> participants = scheduleCenterDO.getParticipants();
//        //日程参与人为空，部门树返回根节点
//        if (participants == null || participants.isEmpty()) {
//            return getRootDept(allDeptList);
//        }
        //所有参与人 deptId +“-”+userId 形式
        Set<Long> detpList = userList.stream().map(item -> Long.valueOf(item.split("-")[0])).collect(Collectors.toSet());

        //去除中间部门节点
        Set<Long> childDeptIds = new HashSet();
        for (Long deptId : detpList) {
            //获取所有下级部门
            List<DeptDO> childDept = new ArrayList();
            deptService.getChildDeptByParentId(deptId, childDept);
            Boolean flag = false;
            for (DeptDO child : childDept) {
                for (Long d : detpList) {
                    if (d.longValue() == child.getId()) {
                        flag = true;
                        break;
                    }
                }
                if (flag) {
                    break;
                }
            }
            if (!flag) {
                childDeptIds.add(deptId);
            }
        }
        List<JSONObject> deptTree = getDeptTree(allDeptList, childDeptIds);
        List<TenantDO> subTenant = tenantService.getSubTenant();
        for (TenantDO tenantDO : subTenant) {
            Boolean flag = false;
            for (JSONObject json : deptTree) {
                if (tenantDO.getId().longValue() == json.getLong("tenantId")) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                for (DeptDO dept : allDeptList) {
                    if (dept.getTenantId().longValue() == tenantDO.getId() && dept.getParentId().longValue() == 0) {
                        JSONObject deptJson = new JSONObject();
                        deptJson.put("id", dept.getId());
                        deptJson.put("label", dept.getName());
                        deptJson.put("leaf", Boolean.FALSE);
                        deptJson.put("type", "dept");
                        deptJson.put("parentId", dept.getParentId());
                        deptJson.put("tenantId", dept.getTenantId());
                        deptJson.put("sort", dept.getSort());
                        deptTree.add(deptJson);
                        break;
                    }
                }
            }
        }
        Collections.sort(deptTree, new Comparator<JSONObject>() {
            public int compare(JSONObject m1, JSONObject m2) {
                int i = m1.getInteger("sort").compareTo(m2.getInteger("sort"));
                return i;
            }
        });
        return deptTree;
    }

    /**
     * 获取部门子部门和部门下的用户
     *
     * @param deptId
     * @return
     */
    @Override
    public List<JSONObject> getSubDeptAndUser(Long deptId) {
        List<DeptDO> deptDOS = deptMapper.selectList(DeptDO::getParentId, deptId);
        List<JSONObject> result = new ArrayList<>();
        for (DeptDO dept : deptDOS) {
            Long aLong = deptMapper.selectCountByParentId(dept.getId());
            JSONObject deptJson = new JSONObject();
            deptJson.put("id", dept.getId());
            deptJson.put("label", dept.getName());
            if (aLong > 0) {
                deptJson.put("leaf", Boolean.FALSE);
            } else {
                deptJson.put("leaf", Boolean.TRUE);

            }
            deptJson.put("type", "dept");
            deptJson.put("parentId", dept.getParentId());
            deptJson.put("tenantId", dept.getTenantId());
            result.add(deptJson);
        }

        List<JSONObject> deptUserList = getDeptUserList(deptId);
        if (!deptUserList.isEmpty()) {
            result.addAll(deptUserList);
        }
        return result;
    }

    //从下往上组装树
    List<JSONObject> getDeptTree(List<DeptDO> deptDOS, Set<Long> selectList) {
        List<JSONObject> result = new ArrayList<>();
        for (DeptDO dept : deptDOS) {
            for (Long deptId : selectList) {
                if (dept.getId().longValue() == deptId) {
                    JSONObject deptJson = new JSONObject();
                    deptJson.put("id", deptId);
                    deptJson.put("label", dept.getName());
                    deptJson.put("leaf", Boolean.FALSE);
                    deptJson.put("type", "dept");
                    deptJson.put("parentId", dept.getParentId());
                    deptJson.put("tenantId", dept.getTenantId());
                    deptJson.put("sort", dept.getSort());
                    List<JSONObject> deptUserList = getDeptUserList(deptId);
                    List<JSONObject> subDept = getSubDept(deptDOS, deptId);
                    if (!subDept.isEmpty()) {
                        deptUserList.addAll(subDept);
                    }
                    deptJson.put("children", deptUserList);
                    result.add(deptJson);
                }
            }
        }
        result = parseParentDept(deptDOS, result);
        return result;
    }

    List<JSONObject> getSubDept(List<DeptDO> deptDOs, Long deptId) {
        List<JSONObject> result = new ArrayList<>();
        for (DeptDO dept : deptDOs) {
            if (dept.getParentId().longValue() == deptId) {
                JSONObject deptJson = new JSONObject();
                deptJson.put("id", dept.getId());
                deptJson.put("label", dept.getName());
                deptJson.put("leaf", Boolean.FALSE);
                deptJson.put("type", "dept");
                deptJson.put("parentId", dept.getParentId());
                deptJson.put("children", new ArrayList<>());
                deptJson.put("sort", dept.getSort());

                result.add(deptJson);
            }
        }
        return result;
    }

    //从叶子节点 往根 组装一个树
    List<JSONObject> parseParentDept(List<DeptDO> deptDOs, List<JSONObject> childList) {
        List<JSONObject> result = new ArrayList();

        //parentId ==0 代表到了根节点
        for (JSONObject json : childList) {
            if (json.getLong("parentId").longValue() == 0) {
                result.add(json);
            }
        }
        Set<Long> parentIdSet = childList.stream().map(item -> (Long) item.get("parentId")).collect(Collectors.toSet());
        //遍历叶子节点、设置父节点
        for (Long parentId : parentIdSet) {
            JSONObject dept = null;
            for (JSONObject json : result) {
                if (json.getLong("id").longValue() == parentId) {
                    //父部门已经存在，在下面的逻辑中，把本叶子节点，添加到也存在的父节点中
                    //该情形时多个叶子节点 拥有同一个根
                    dept = json;
                    break;
                }
            }
            //根节点
            for (DeptDO deptDO : deptDOs) {
                if (deptDO.getId().longValue() == parentId) {
                    List<JSONObject> deptUserList = new ArrayList<>();
                    //如果跟不存在，创建一个父部门对象
                    if (dept == null) {
                        dept = new JSONObject();
                        dept.put("id", deptDO.getId());
                        dept.put("label", deptDO.getName());
                        dept.put("leaf", Boolean.FALSE);
                        dept.put("type", "dept");
                        dept.put("parentId", deptDO.getParentId());
                        dept.put("tenantId", deptDO.getTenantId());
                        dept.put("sort", deptDO.getSort());
                        result.add(dept);
                    } else {
                        //获取根已经存在的，则把 parentId 节点 挂到 dept 部门下
                        //即把 本部门 添加到父部门的children 中
                        deptUserList = (List<JSONObject>) dept.get("children");
                    }
                    //添加 选择的子部门
                    for (JSONObject item : childList) {
                        if ((Long) item.get("parentId") == deptDO.getId().longValue()) {
                            deptUserList.add(item);
                        }
                    }
                    //添加 本部门的兄弟部门到 父部门的 children 中
                    //获取部门的 所有子部门，
                    List<JSONObject> subDept = getSubDept(deptDOs, deptDO.getId());
                    if (!subDept.isEmpty()) {
                        for (JSONObject json : subDept) {
                            Long id = json.getLong("id");
                            Boolean flag = false;
                            for (JSONObject item : childList) {
                                Long id1 = item.getLong("id");
                                if (id.longValue() == id1) {
                                    flag = true;
                                    break;
                                }
                            }
                            //在所有部门中，排出childList
                            if (!flag) {
                                deptUserList.add(json);
                            }
                        }
                    }
                    //添加本部门 下的人员
                    List<JSONObject> userList = getDeptUserList(deptDO.getId());
                    if (!userList.isEmpty()) {
                        deptUserList.addAll(userList);
                    }
                    dept.put("children", deptUserList);
                    if (deptDO.getParentId() != 0) {
                        return parseParentDept(deptDOs, result);
                    }
                    break;
                }
            }
        }
        return result;
    }

    List<JSONObject> getRootDept(List<DeptDO> deptDOS) {
        List<JSONObject> result = new ArrayList<>();

        List<TenantDO> subTenant = tenantService.getSubTenant();
        for (DeptDO deptDO : deptDOS) {

            if (deptDO.getParentId() != null && deptDO.getParentId() == 0 && isContain(subTenant, deptDO.getTenantId())) {
                JSONObject dept = new JSONObject();
                dept.put("id", deptDO.getId());
                dept.put("label", deptDO.getName());
                dept.put("leaf", Boolean.FALSE);
                dept.put("type", "dept");
                dept.put("sort", deptDO.getSort());
                List<JSONObject> deptUserList = getDeptUserList(deptDO.getId());
                dept.put("children", deptUserList);
                result.add(dept);
            }
        }
        //按照sort 字段排序
        Collections.sort(result, new Comparator<JSONObject>() {
            public int compare(JSONObject m1, JSONObject m2) {
                return m1.getInteger("sort").compareTo(m2.getInteger("sort"));
            }
        });
        return result;
    }

    Boolean isContain(List<TenantDO> subTenant, Long tenantId) {
        for (TenantDO tenantDO : subTenant) {
            if (tenantDO.getId().longValue() == tenantId) {
                return true;
            }
        }
        return false;
    }

    private List<JSONObject> getDeptUserList(Long deptId) {
        MPJLambdaWrapperX<AdminUserDO> wrapper = new MPJLambdaWrapperX<>();
        wrapper.distinct();
        wrapper.and(wrap -> wrap.eq(UserDeptDO::getDeptId, deptId)
                .or().eq(AdminUserDO::getDeptId, deptId)
        );
        wrapper.leftJoin(UserDeptDO.class, UserDeptDO::getUserId, AdminUserDO::getId);
        List<AdminUserDO> adminUserDOS = userMapper.selectList(wrapper);
        // List<AdminUserDO> adminUserDOS = userMapper.selectList(AdminUserDO::getDeptId, deptId);
        if (adminUserDOS.isEmpty()) {
            return new ArrayList<>();
        }
        List<JSONObject> userList = adminUserDOS.stream().map(item -> {
            JSONObject user = new JSONObject();
            user.put("id", deptId + "-" + item.getId());
            user.put("label", item.getNickname());
            user.put("leaf", Boolean.TRUE);
            user.put("type", "user");
            return user;
        }).collect(Collectors.toList());
        return userList;
    }

}